﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Collections.Specialized;
using System.IO;
using System.Web;
using System.Xml;
using System.Threading;
using System.Web.Configuration;

namespace MyLib
{
    public static class ConfigurationManager
    {
        static NameValueCollection _appSettings = new NameValueCollection();
        static ConnectionStringSettingsCollection _conectionStrings = new ConnectionStringSettingsCollection();
        static System.Configuration.Configuration _conf = null;
        static ConfigFileType _configFileType;
        static string _fileName;
        static FileSystemWatcher _watcher = new FileSystemWatcher();

        static ConfigurationManager()
        {
            Config(ConfigFileType.WebConfig, "");
        }
        
        public static void Config(ConfigFileType configFileType, string fileName)
        {            
            _configFileType = configFileType;
            _fileName = fileName;
            ClearCache();
            if (configFileType == ConfigFileType.WebConfig)
            {
                _appSettings = System.Configuration.ConfigurationManager.AppSettings;
                _conectionStrings = System.Configuration.ConfigurationManager.ConnectionStrings;
            }
            else
            {
                //读取配置
                ReadConfig(fileName);
                //添加对文件的监视
                FileInfo file = new FileInfo(fileName);
                _watcher.Path = file.DirectoryName;
                _watcher.NotifyFilter = NotifyFilters.LastWrite;
                _watcher.Filter = fileName;
                _watcher.Changed += new FileSystemEventHandler(_watcher_Changed);
                _watcher.EnableRaisingEvents = true;
            }
        }

        static void ClearCache()
        {
            CacheUtil.ClearCache();
            _appSettings = new NameValueCollection();
            _conectionStrings = new ConnectionStringSettingsCollection();
        }

        static void _watcher_Changed(object sender, FileSystemEventArgs e)
        {
            ClearCache();
            //重新读取配置
            ReadConfig(_fileName);
        }

        static void ReadConfig(string fileName)
        {
            ExeConfigurationFileMap map = new ExeConfigurationFileMap();
            map.ExeConfigFilename = fileName;
            _conf = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
            if (_conf != null)
            {
                foreach (KeyValueConfigurationElement keyvalue in _conf.AppSettings.Settings)
                {
                    _appSettings.Add(keyvalue.Key, keyvalue.Value);
                }

                _conectionStrings = _conf.ConnectionStrings.ConnectionStrings;
            }
        }

        public static void SaveAppSettings(string key, string value)
        {
            string filename = "";
            if (HttpContext.Current != null)
            {
               filename= HttpContext.Current.Server.MapPath("~") + @"\web.config";
            }
            if (_configFileType == ConfigFileType.FileConfig)
            {
                filename = _fileName;
            }
            if (string.IsNullOrEmpty(filename))
            {
                return;
            }
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(filename);
            XmlNodeList appnodes = xmldoc.SelectNodes("//appSettings//add[@key='"+key+"']");
            foreach (XmlNode node in appnodes)
            {
                node.Attributes["value"].Value = value;               
            }            
            xmldoc.Save(filename);
            if (_configFileType == ConfigFileType.WebConfig)
            {
                _appSettings=new NameValueCollection();
                foreach (KeyValueConfigurationElement keyvalue in WebConfigurationManager.OpenWebConfiguration("~").AppSettings.Settings)
                {
                    _appSettings.Add(keyvalue.Key, keyvalue.Value);
                }
            }
        }

        public static void SaveConnectionString(string name,string connectionString)
        {
            string filename = "";
            if (HttpContext.Current != null)
            {
                filename = HttpContext.Current.Server.MapPath("~") + @"\web.config";
            }
            if (_configFileType == ConfigFileType.FileConfig)
            {
                filename = _fileName;
            }
            if (string.IsNullOrEmpty(filename))
            {
                return;
            }
            XmlDocument xmldoc = new XmlDocument();
            xmldoc.Load(filename);
            XmlNodeList nodes = xmldoc.SelectNodes("//connectionStrings//add");
            foreach (XmlNode node in nodes)
            {
                if (node.Attributes["name"].Value.Trim().ToUpper() == name.Trim().ToUpper())
                {
                    node.Attributes["connectionString"].Value = connectionString;
                }
            }
           
            xmldoc.Save(filename);
            if (_configFileType == ConfigFileType.WebConfig)
            {
                _conectionStrings= WebConfigurationManager.OpenWebConfiguration("~").ConnectionStrings.ConnectionStrings;
            }

        }

        public static NameValueCollection AppSettings
        {
            get
            {
                return _appSettings;
            }
            set
            {
                _appSettings = value;
            }
        }

        public static ConnectionStringSettingsCollection ConnectionStrings
        {
            get
            {
                return _conectionStrings;
            }
            set
            {
                _conectionStrings = value;
            }
        }

        public static object GetSection(string sectionName)
        {
            if (_configFileType == ConfigFileType.FileConfig)
            {
                if (_conf != null)
                {
                    ConfigurationSection section=_conf.GetSection(sectionName);
                    if (section != null)
                    {
                        string str = section.SectionInformation.Type;
                        IConfigurationSectionHandler handler = ReflectUtil.CreateInstance(ReflectUtil.GetType(str)) as IConfigurationSectionHandler;
                        XmlDocument xmldoc = XmlDocument;
                        XmlNode node = xmldoc.SelectSingleNode("//" + sectionName);
                        return handler.Create(null, null, node);
                    }
                    else
                    {
                        return null;
                    }
                }
            }

            return System.Configuration.ConfigurationManager.GetSection(sectionName);
        }

        public static ConfigFileType ConfigFileType
        {
            get
            {
                return _configFileType;
            }
        }

        public static string FileName
        {
            get
            {
                return _fileName;
            }
            set
            {
                Config(ConfigFileType.FileConfig, value);
            }
        }

        static XmlDocument _xmlDoc;
        public static XmlDocument XmlDocument
        {
            get
            {
                if (_xmlDoc == null)
                {
                    if (!string.IsNullOrEmpty(_fileName))
                    {
                        _xmlDoc = new System.Xml.XmlDocument();
                        _xmlDoc.Load(_fileName);
                    }
                }
                return _xmlDoc;
            }
        }
    }

    public enum ConfigFileType
    {
        WebConfig,
        FileConfig
        //    ,
        //EmbeddedConfig,
        //HttpConfig
    }

}
